# -*- coding: utf-8 -*-
"""
Database operations/MySql Aiomysql/test01.py
"""
import asyncio
import aiomysql
from aiomysql import Cursor, DictCursor, SSCursor, SSDictCursor

sql_create_user_table = """CREATE TABLE IF NOT EXISTS `user` (
  `user_id` int NOT NULL AUTO_INCREMENT,
  `user_name` varchar(500) COLLATE utf8mb4_bin DEFAULT NULL,
  PRIMARY KEY (`user_id`)
);"""


async def connect():
    """
    数据库连接
    :return:
    """
    con = await aiomysql.connect(host="127.0.0.1", user='tornado',
                                 password="tornado",
                                 db='tornado_db_02', port=3306, unix_socket=None,
                                 charset='', sql_mode=None,
                                 read_default_file=None, use_unicode=None,
                                 client_flag=0, cursorclass=Cursor, init_command=sql_create_user_table,
                                 connect_timeout=None, read_default_group=None,
                                 autocommit=True, echo=False,
                                 local_infile=False, loop=None, ssl=None, auth_plugin='',
                                 program_name='', server_public_key=None)
    return con


async def settings_connect(con):
    """
    设置数据库会话
    :return:
    """
    # aiomysql.autocommit(value): 设置数据库会话启用/禁用自动提交状态。
    await con.autocommit(False)
    # aiomysql.select_db(db): 设置连接会话中的数据库名。
    await con.select_db('tornado_db_02')


def print_connect(con):
    """
    打印数据库会话信息
    :return:
    """
    # aiomysql.get_autocommit(): 获取当前数据库会话的自动提交状态
    print(f'aiomysql.get_autocommit(): {con.get_autocommit()}')

    # aiomysql.host: 获取数据库会话地址
    print(f'aiomysql.host:             {con.host}')

    # aiomysql.port: 获取数据库会话端口
    print(f'aiomysql.port:             {con.port}')

    # aiomysql.unix_socket: 获取数据库会话端口
    print(f'aiomysql.unix_socket:      {con.unix_socket}')

    # aiomysql.db: 获取当前数据库名
    print(f'aiomysql.db:               {con.db}')

    # aiomysql.user: 获取数据库会话用户名
    print(f'aiomysql.user:             {con.user}')

    # echo: 返回echo模式状态。
    print(f'aiomysql.echo:             {con.echo}')

    # aiomysql.encoding:  获取数据库会话编码
    print(f'aiomysql.encoding:         {con.encoding}')

    # aiomysql.charset： 获取当前数据库会话字符集
    print(f'aiomysql.charset:          {con.charset}')


async def process_users(con):
    """
    处理用户信息
    :param con:
    :return:
    """
    cursor = await con.cursor()
    # DictCursor: 查询结果将作为字典列表返回。
    # cursor = await con.cursor(DictCursor)

    # closed: 获取当前游标状态。
    print(f'cursor.closed:             {cursor.closed}')

    # fetchone(): 返回单个的元组数据，如果没有结果返回`None`。
    await cursor.execute(f'select * from user')
    print(f'cursor.fetchall():         {await cursor.fetchall()}')
    # lastrowid: 返回自增主键行号。
    print(f'cursor.rowcount:           {cursor.rowcount}')

    # fetchmany(size=None): 返回指定数量的元组数据，如未指定数据，则返回单个元组数据；如没有查询结果返回`None`。
    await cursor.execute(f'select * from user')
    print(f'cursor.fetchone():         {await cursor.fetchone()}')
    # rownumber: 行索引。
    print(f'cursor.rownumber:          {cursor.rownumber}')

    # fetchall(): 返回所有的元组数据，如没有结果返回空元组。
    await cursor.execute(f'select * from user')
    print(f'cursor.fetchmany():        {await cursor.fetchmany(size=10)}')
    # arraysize: `Cursor.fetchmany()`返回的行数。
    print(f'cursor.arraysize:          {cursor.arraysize}')

    # aiomysql.begin(): 数据库会话事务开始。
    await con.begin()
    exe = await cursor.execute(f'insert into user(user_name) values(%s)', 'tornado')
    # 打印受影响行数
    print(f'cursor.execute:            {exe}')

    # lastrowid: 返回自增主键行号。
    print(f'cursor.lastrowid:          {cursor.lastrowid}')

    # aiomysql.commit(): 提交数据库会话事务。
    # await con.commit()
    # aiomysql.rollback(): 数据库会话事务回滚。
    await con.rollback()

    # aiomysql.begin(): 数据库会话事务开始。
    await con.begin()
    # executemany(query, args): 执行复数参数的数据库操作。
    exe = await cursor.executemany(f'insert into user(user_name) values(%s)', ['tornado', 'tornado_01'])
    # 打印受影响行数
    print(f'cursor.executemany:        {exe}')

    # lastrowid: 返回自增主键行号。
    print(f'cursor.lastrowid:          {cursor.lastrowid}')

    # aiomysql.commit(): 提交数据库会话事务。
    # await con.commit()
    # aiomysql.rollback(): 数据库会话事务回滚。
    await con.rollback()

    # close(): 主动关闭当前游标。
    await cursor.close()


async def main():
    # 开启数据库会话
    con = await connect()

    # 设置数据库会话
    await settings_connect(con)

    # 打印数据库会话
    print_connect(con)

    # 处理用户信息
    await process_users(con)

    # 关闭数据库会话
    # aiomysql.close(): 关闭数据库会话。
    con.close()


if __name__ == '__main__':
    asyncio.run(main())
